/*
 * GridSpace_test.cpp
 *
 *  Created on: Nov 13, 2011
 *      Author: yi
 */

#include "mbuild.h"
#include <iostream>
#include "time.h"
#include "stdio.h"
using namespace std;

int test(void) {
	GridSpace space=GridSpace();
	// TODO: Uninitialized space will be empty:
	unsigned long nx,ny,nz,n=space.get_dimension(nx,ny,nz);
	double dvdx,dvdy,dvdz,dx,dy,dz,x0,y0,z0,v,x,y,z;
	space.get_grid_size(dx,dy,dz);
	space.get_origin(x0,y0,z0);
	cout<<"Uninitialized space"<<endl;
	cout<<"Nx:"<<nx<<",Ny:"<<ny<<",Nz:"<<nz<<"    Total(Nx*Ny*Nz)="<<n<<endl;
	cout<<"dx:"<<dx<<",dy:"<<dy<<",dz:"<<dz<<"    volume="<<dx*dy*dz<<endl;
	cout<<"X0:"<<x0<<",Y0:"<<y0<<",Z0:"<<z0<<endl;
	cout<<"Should not be able to get values from it right now!\n";
	try {
		space.getValue(10,20,12);
	}
	catch(GridSpaceNotInitialized& error) {
		cout<<"Caught Exception: GridSpaceNotInitialized\n";
	}
	cout<<"Should not be able to get derivatives from it right now!\n";
	try {
		space.getDerivatives(10,20,12,dvdx,dvdy,dvdz);
	}
	catch(GridSpaceNotInitialized& error) {
		cout<<"Caught Exception: GridSpaceNotInitialized\n";
	}
    // TODO: Setup and Initialize the space:
	bool NoError=false;
	while (!NoError) {
		cout<<"Input nx:";
		cin>>nx;
		cout<<"Input ny:";
		cin>>ny;
		cout<<"Input nz:";
		cin>>nz;
		cout<<"Input X0:";
		cin>>x0;
		cout<<"Input Y0:";
		cin>>y0;
		cout<<"Input Y0:";
		cin>>y0;
		cout<<"Input dx:";
		cin>>dx;
		cout<<"Input dy:";
		cin>>dy;
		cout<<"Input dz:";
		cin>>dz;
		NoError=true;
		try {
			space.set_origin(x0,y0,z0);
			space.set_grid_size(dx,dy,dz);
			space.set_dimension(nx,ny,nz);
		} catch(GridSizeIsNotPositive& error) {
			cout <<"Caught Exception: GridSizeIsNotPositive\n";
			NoError=false;
		} catch(TooBigForThisPlatform& error) {
			cout <<"Caught Exception: TooBigForThisPlatform\n";
			NoError=false;
		}
	}
	cout <<"Initialize the space with:";
	cin>>v;
	NoError=false;
	while(!NoError){
		NoError=true;
		try {
			space.initialize(v);
		} catch(NotEnoughMemory& error) {
			cout<<"Caught Not Enough Memory"<< endl;
			NoError=false;
		}
	}
	// TODO: The value of grid space after initialization:
	n=space.get_dimension(nx,ny,nz);
	space.get_grid_size(dx,dy,dz);
	space.get_origin(x0,y0,z0);
	cout<<"Initialized:"<<endl;
	cout<<"Nx:"<<nx<<",Ny:"<<ny<<",Nz:"<<nz<<"    Total(Nx*Ny*Nz)="<<n<<endl;
	cout<<"dx:"<<dx<<",dy:"<<dy<<",dz:"<<dz<<"    volume="<<dx*dy*dz<<endl;
	cout<<"X0:"<<x0<<",Y0:"<<y0<<",Z0:"<<z0<<endl;
	NoError=false;
	while(!NoError){
		NoError=true;
		try {
			cout<<"Input a position to get value:\n";
			cout<<"x:";
			cin>>x;
			cout<<"y:";
			cin>>y;
			cout<<"z:";
			cin>>z;
			v=space.getValue(x,y,z);
			v=space.getDerivatives(x,y,z,dvdx,dvdy,dvdz);
			cout<<"value:"<<v<<endl;
			cout<<"dv/dx: "<<dvdx<<" ,dv/dy: "<<dvdy<<" ,dv/dz: "<<dvdz<<endl;
		} catch(OutOfRange& error) {
			cout<<"Caught Exception: OutOfRange\n";
			NoError=false;
		}
	}
    // TODO: Clear the Space.
	cout<<"Re-initialized to 1.0.\n";
	space.clear(1.0);
	NoError=false;
	while(!NoError){
		NoError=true;
		try {
			cout<<"Input a position to get value:\n";
			cout<<"x:";
			cin>>x;
			cout<<"y:";
			cin>>y;
			cout<<"z:";
			cin>>z;
			v=space.getValue(x,y,z);
			v=space.getDerivatives(x,y,z,dvdx,dvdy,dvdz);
			cout<<"value:"<<v<<endl;
			cout<<"dv/dx: "<<dvdx<<" ,dv/dy: "<<dvdy<<" ,dv/dz: "<<dvdz<<endl;
		} catch(OutOfRange& error) {
			cout<<"Caught Exception: OutOfRange\n";
			NoError=false;
		}
	}
	// TODO: Test copy space.
	GridSpace newspace;
	space.copyto(&newspace);
	cout<<"Copied to new space.\n";
	NoError=false;
	while(!NoError){
		NoError=true;
		try {
			cout<<"Input a position to get value:\n";
			cout<<"x:";
			cin>>x;
			cout<<"y:";
			cin>>y;
			cout<<"z:";
			cin>>z;
			v=newspace.getValue(x,y,z);
			v=newspace.getDerivatives(x,y,z,dvdx,dvdy,dvdz);
			cout<<"value:"<<v<<endl;
			cout<<"dv/dx: "<<dvdx<<" ,dv/dy: "<<dvdy<<" ,dv/dz: "<<dvdz<<endl;
		} catch(OutOfRange& error) {
			cout<<"Caught Exception: OutOfRange\n";
			NoError=false;
		}
	}
	// TODO: Test very big space.
	for(nx=50;nx<1000;nx+=50) {
		space.set_dimension(nx,nx,nx);
		clock_t t1=clock();
		space.initialize(0);
		clock_t t2=clock();
		cout<<"Time to initialize a"<<nx<<"^3 maxtrix:"<<double(t2-t1)*1000/CLOCKS_PER_SEC<<" ms.\n";
	}
	return 1;
}

int main(void) {
	test();
	return 0;
}


